[Python] 不正な名前のモジュールを頑張ってimportする方法
こんにちは。サービス部の武田です。
Pythonでは変数名などに付けられる名前として命名規約があります。モジュールやパッケージ名も同様です。ところで、一般的にモジュールはOSのファイル、パッケージはディレクトリがそれぞれ対応します。そのため、Pythonとしては不正な(命名規約から外れた)名前をファイルやディレクトリにつけることも可能です。
その場合、もちろん不正な名前なので別ファイルからimportができません。そのため、通常であればファイル名なりを変更するべきです。ですが、何らかの理由で今すぐ名前を変更できないが、importして使いたいというケースに出会うこともあるでしょう。今回はその方法を紹介します。再度言いますが、まずは名前変更を検討してください。
不正な名前の例
たとえばPythonの予約語はモジュール名として不正です。ここではlambda.py
というファイルを作成してみます。
$ tree . ├── main.py └── test ├── __init__.py └── lambda.py
lambda.py
は関数を定義しているだけです。
def hello(): print("Hello World!")
このファイルを別ファイルからimportしてみます。
import test.lambda test.lambda.hello()
実行しようとしてもできません。
File "/tmp/main.py", line 1 import test.lambda ^ SyntaxError: invalid syntax
import_moduleを使う方法
先ほど見たように、予約語などはinvalid syntax
となってimportできませんでした。そこで文字列として指定する方法に切り替えます。importlib.import_module
は引数としてimportしたいモジュールを指定し、動的にインポートするための関数です。
import importlib mymod = importlib.import_module("test.lambda") mymod.hello()
この方法であれば、問題なくimportして実行できます。
$ python3 main.py Hello World!
SourceFileLoaderを使う方法
別の方法として、ロードしたいファイルを直接指定する方法もあります。同じように動的にインポートできますが、手順が先ほどより増えています。
from importlib import machinery, util from pathlib import Path mod_path = Path("test/lambda.py") loader = machinery.SourceFileLoader(str(mod_path), str(mod_path)) spec = util.spec_from_file_location(str(mod_path), mod_path, loader=loader) mymod = util.module_from_spec(spec) spec.loader.exec_module(mymod) mymod.hello()
この方法でも、問題なくimportして実行できます。
$ python3 main.py Hello World!
まとめ
最初にも言いましたが、まずは不正な名前を付けないようにするのが先決です。それでも付けてしまい、かつ変えられない事情があり、何とかimportしたいんだ!という状況になってしまった時に、思い出してもらえればと思います。